using System.Collections.Frozen;
using InfiniteCraft.Models;

namespace InfiniteCraft.Services;

public class Recipes
{
    private const string BasicPrefix = "Basic:";

    private readonly FrozenSet<Receipt> _recipes;
    private readonly FrozenSet<string> _basicElementNames;

    private Recipes(List<Receipt> recipes, List<string> basicElementNames)
    {
        _recipes = recipes.ToFrozenSet();
        _basicElementNames = basicElementNames.ToFrozenSet();
    }

    public static Recipes FromFile(string path)
    {
        var lines = File.ReadAllLines(path);
        var recipes = new List<Receipt>();
        var basicElementNames = new List<string>();

        foreach (var line in lines)
        {
            if (string.IsNullOrEmpty(line))
                continue;

            if (line.Contains(BasicPrefix))
            {
                basicElementNames.Add(line.Split(BasicPrefix)[1].Trim());
                continue;
            }

            var splittedByEqual = line.Split("=");
            var splittedByPlus = splittedByEqual[0].Split("+");

            var first = splittedByPlus[0].Trim();
            var second = splittedByPlus[1].Trim();
            var result = splittedByEqual[1].Trim();

            recipes.Add(new Receipt(first, second, result));
        }

        return new Recipes(recipes, basicElementNames);
    }

    public FrozenSet<string> GetBasicCraftElementNames()
    {
        return _basicElementNames;
    }

    public string? TryToCraft(string srcName, string targetName)
    {
        if (string.IsNullOrEmpty(srcName) || string.IsNullOrEmpty(targetName))
            return null;

        var craftedElement = _recipes.Where(x => !string.IsNullOrEmpty(x.Second)
                                                 &&
                                                 ((x.First.ToLower() == srcName.Trim().ToLower() &&
                                                   x.Second.ToLower() == targetName.Trim().ToLower())
                                                  ||
                                                  (x.Second.ToLower() == srcName.Trim().ToLower() &&
                                                   x.First.ToLower() == targetName.Trim().ToLower())))
            .FirstOrDefault();

        if (craftedElement is null)
            return null;

        return craftedElement.Result;
    }
}